package com.ants.boot.system.service.impl;

import com.ants.boot.core.Response;
import com.ants.boot.core.enums.DataStatusEnum;
import com.ants.boot.core.security.user.LoginUser;
import com.ants.boot.model.BaseModel;
import com.ants.boot.system.dao.SysUserMapper;
import com.ants.boot.system.domain.SysMenu;
import com.ants.boot.system.domain.SysUser;
import com.ants.boot.system.domain.SysUserRole;
import com.ants.boot.system.dto.sysuser.*;
import com.ants.boot.system.service.SysMenuService;
import com.ants.boot.system.service.SysUploadService;
import com.ants.boot.system.service.SysUserRoleService;
import com.ants.boot.system.service.SysUserService;
import com.ants.boot.system.vo.sysuser.LoginUserInfoVo;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.GrantedAuthority;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.crypto.bcrypt.BCryptPasswordEncoder;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.multipart.MultipartFile;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author 蚂蚁会花呗
 * @date 2021/11/26 14:55
 */
@Service
public class SysUserServiceImpl extends ServiceImpl<SysUserMapper, SysUser> implements SysUserService {

    /**
     * 默认密码
     */
    private static final String DEFAULT_PASSWORD = "123456";


    @Autowired
    private SysUploadService sysUploadService;


    @Autowired
    private SysMenuService sysMenuService;

    @Autowired
    private SysUserRoleService sysUserRoleService;


    @Override
    public SysUser findByUsername(String username) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SysUser::getUsername,username)
                .eq(BaseModel::getStatus, DataStatusEnum.NORMAL_STATUS.getValue());
        return this.getOne(queryWrapper);
    }

    @Override
    public SysUser findByPhoneNumber(String phoneNumber) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SysUser::getPhoneNumber,phoneNumber)
                .eq(BaseModel::getStatus, DataStatusEnum.NORMAL_STATUS.getValue());
        return this.getOne(queryWrapper);
    }

    @Override
    public LoginUserInfoVo getUserInfo(Integer userId) {
        LoginUserInfoVo vo = new LoginUserInfoVo();
        Authentication authentication = SecurityContextHolder.getContext().getAuthentication();
        LoginUser loginUser = (LoginUser)authentication.getPrincipal();
        for (GrantedAuthority ga : authentication.getAuthorities()){
            vo.getRoles().add(ga.getAuthority());
        }
        vo.setId(loginUser.getUserId());
        vo.setUsername(loginUser.getUsername());
        vo.setAge(loginUser.getAge());
        vo.setAvatar(loginUser.getAvatar());
        vo.setEmail(loginUser.getEmail());
        vo.setNickName(loginUser.getNickName());
        vo.setPhoneNumber(loginUser.getPhoneNumber());
        vo.setRemark(loginUser.getRemark());
        //获取用户所具有的权限
        List<String> perms = sysMenuService.findMenuPermsByUserId(userId).stream().map(SysMenu::getPerms).filter(s -> !s.equals("")).collect(Collectors.toList());
        vo.getPermissions().addAll(perms);
        return vo;
    }

    @Override
    public IPage<SysUser> pageInfo(QueryUserDto dto) {
        Page<SysUser> page = new Page<>(dto.getPageNum(),dto.getPageSize());
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        if (StringUtils.isNotBlank(dto.getUsername())){
            queryWrapper.lambda()
                    .like(SysUser::getUsername,dto.getUsername());
        }
        if (StringUtils.isNotBlank(dto.getStatus())){
            queryWrapper.and(wrapper ->wrapper.lambda().eq(SysUser::getStatus,dto.getStatus()));
        }
        if (StringUtils.isNotBlank(dto.getCreateTime())){
            queryWrapper.and(wrapper ->wrapper.lambda().ge(SysUser::getCreateTime,dto.getCreateTime()));
        }
        IPage<SysUser> iPage = this.page(page,queryWrapper);
        iPage.getRecords().forEach(sysUser -> {sysUser.setPassword("");});
        return iPage;
    }

    @Override
    @Transactional
    public SysUser addUser(AddUserDto dto) {
        boolean flag = false;
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(dto,sysUser);
        if (StringUtils.isNotBlank(dto.getPassword())){
            sysUser.setPassword(setBCryptPassword(DEFAULT_PASSWORD));
        }else{
            sysUser.setPassword(sysUser.getPassword());
        }
        flag = this.save(sysUser);
        if (!dto.getRoleIds().isEmpty() && flag){
            flag = saveSysUserRole(dto.getRoleIds(),sysUser.getId());
        }
        if (flag){
            return sysUser;
        }
        return null;
    }

    @Override
    @Transactional
    public boolean updateUser(UpdateUserDto dto) {
        SysUser user = this.getById(dto.getId());
        boolean flag = false;
        SysUser sysUser = new SysUser();
        BeanUtils.copyProperties(dto,sysUser);
        sysUser.setPassword(user.getPassword());
        sysUser.setStatus(Integer.valueOf(dto.getStatus()));
        flag = this.saveOrUpdate(sysUser);
        sysUserRoleService.delSysUserRole(dto.getId());
        if (!dto.getRoleIds().isEmpty() && flag){
            flag = saveSysUserRole(dto.getRoleIds(),dto.getId());
        }
        return flag;
    }

    @Override
    @Transactional
    public boolean delUser(List<Integer> ids) {
        ids.forEach(id->{
            this.removeById(id);
            sysUserRoleService.delSysUserRole(id);
        });
        return true;
    }

    @Override
    public boolean updateStatus(Integer roleId, Integer status) {
        UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .set(BaseModel::getStatus,status)
                .eq(SysUser::getId,roleId);
        return this.update(updateWrapper);
    }

    @Override
    public boolean resetPassword(ResetPasswordDto dto) {
        UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .set(SysUser::getPassword,setBCryptPassword(dto.getNewPassword()))
                .eq(SysUser::getId,dto.getId());
        return this.update(updateWrapper);
    }

    @Override
    public String uploadAvatar(MultipartFile file) {
        String path = sysUploadService.uploadImgBlob(file);
        return path;
    }

    @Override
    public boolean updateAvatar(UpdateAvatarDto dto) {
        UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .set(SysUser::getAvatar,dto.getPath())
                .eq(SysUser::getUsername,dto.getUsername());
        return this.update(updateWrapper);
    }

    @Override
    public boolean updateProfile(UpdateProfileDto dto) {
        UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .set(SysUser::getNickName,dto.getNickName())
                .set(SysUser::getPhoneNumber,dto.getPhoneNumber())
                .set(SysUser::getEmail,dto.getEmail())
                .set(SysUser::getSex,dto.getSex())
                .eq(SysUser::getUsername,dto.getUsername());
        return this.update(updateWrapper);
    }

    @Override
    public Response updatePassword(UpdatePasswordDto dto) {
        SysUser sysUser = this.findByUsername(dto.getUsername());
        BCryptPasswordEncoder encoder = new BCryptPasswordEncoder();
        if (!encoder.matches(dto.getOldPassword(),sysUser.getPassword())){
            return Response.fail("原密码不正确！");
        }
        String password = new BCryptPasswordEncoder().encode(dto.getNewPassword());
        UpdateWrapper<SysUser> updateWrapper = new UpdateWrapper<>();
        updateWrapper.lambda()
                .set(SysUser::getPassword,password)
                .eq(SysUser::getUsername,dto.getUsername());
        boolean result = this.update(updateWrapper);
        if (!result){
            return Response.fail();
        }
        return Response.ok();
    }

    @Override
    public SysUser findByOpenId(String openid) {
        QueryWrapper<SysUser> queryWrapper = new QueryWrapper<>();
        queryWrapper.lambda()
                .eq(SysUser::getOpenid,openid);
        return this.getOne(queryWrapper);
    }

    /**
     * 加密密码
     * @param password
     * @return
     */
    private String setBCryptPassword(String password){
        return new BCryptPasswordEncoder().encode(password);
    }

    /**
     * 新增关联
     * @param list
     * @param userId
     * @return
     */
    private boolean saveSysUserRole(List<Integer> list,Integer userId){
        List<SysUserRole> sysUserRoles = new ArrayList<>();
        list.forEach(role->{
            sysUserRoles.add(new SysUserRole(userId,role));
        });
        return sysUserRoleService.saveBatch(sysUserRoles);
    }


}
